//
//  SYCircleCountingLabel.m
//  SYBaseProject
//
//  Created by sunshine on 2018/10/30.
//  Copyright ©YYB 2018年 SY. All rights reserved.
//

#import "CSCircleCountingLabel.h"

@interface CSCircleCountingLabel ()

@property(nonatomic, strong) CADisplayLink *playLink;
@property(nonatomic, assign) NSInteger displayPerSecond;

@property(nonatomic, assign) CGFloat fromValue;
@property(nonatomic, assign) CGFloat toValue;

@property(nonatomic, assign) CGFloat increaseValue;
@property(nonatomic, assign) CGFloat perValue;

@end

@implementation CSCircleCountingLabel

- (instancetype)init {
    if (self = [super init]) {
        [self initValues];
    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self initValues];
    }
    return self;
}

- (void)awakeFromNib {
    [super awakeFromNib];
    [self initValues];
}

- (void)initValues {
    _duration = 2.0;
    _displayPerSecond = 30;
}

- (void)countingFrom:(CGFloat)fromValue to:(CGFloat)toValue {
    [self countingFrom:fromValue to:toValue duration:_duration];
}

- (void)countingFrom:(CGFloat)fromValue to:(CGFloat)toValue duration:(CGFloat)duration {
    _fromValue = fromValue;
    _toValue = toValue;
    _duration = duration;

    _increaseValue = _fromValue;
    _perValue = (_toValue - _fromValue) / (_duration == 0 ? 1 : (_displayPerSecond * _duration));

    if (self.playLink) {
        [self.playLink invalidate];
        self.playLink = nil;
    }

    CADisplayLink *playLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(countingAction)];
    playLink.preferredFramesPerSecond = _displayPerSecond;
    [playLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    [playLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:UITrackingRunLoopMode];
    self.playLink = playLink;
}

- (void)countingAction {
    _increaseValue += _perValue;

    if (_fromValue < _toValue) {
        if (_increaseValue >= _toValue) {
            [self stopDisplayLink];
        }
    } else {
        if (_increaseValue <= _toValue) {
            [self stopDisplayLink];
        }
    }

#ifndef weakify
    #if DEBUG
        #if __has_feature(objc_arc)
            #define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object;
        #else
            #define weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object;
        #endif
    #else
        #if __has_feature(objc_arc)
            #define weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object;
        #else
            #define weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object;
        #endif
    #endif
#endif


#ifndef strongify
    #if DEBUG
        #if __has_feature(objc_arc)
            #define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object;
        #else
            #define strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object;
        #endif
    #else
        #if __has_feature(objc_arc)
            #define strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object;
        #else
            #define strongify(object) try{} @finally{} __typeof__(object) object = block##_##object;
        #endif
    #endif
#endif

    @weakify(self);
    dispatch_async(dispatch_get_main_queue(), ^{
      @strongify(self);
      self.text = [NSString stringWithFormat:@"%03d", (int)self->_increaseValue / 2];
    });
}

- (void)stopDisplayLink {
    [self.playLink invalidate];
    self.playLink = nil;

    _increaseValue = _toValue;
}

@end
